package com.java.base.lock;

import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class AQSTest {

    static ReentrantLock reentrantLock = new ReentrantLock(true);
    static Semaphore semaphore = new Semaphore(3);
    static CountDownLatch countDownLatch = new CountDownLatch(3);
    static CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
    static Exchanger<String> exchanger = new Exchanger<>();

    SynchronousQueue<String> synchronousQueue = new SynchronousQueue<>();


    public static void main(String[] args) throws InterruptedException, BrokenBarrierException {

        await();

    }


    public static void await() throws InterruptedException {
        Condition condition = reentrantLock.newCondition();

        new Thread(() -> {
            try {
                reentrantLock.lock();
                condition.await();
                reentrantLock.unlock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("END");
        }).start();

        Thread.sleep(100);
        reentrantLock.lock();
        System.out.println("MAIN");
        condition.signal();
        reentrantLock.unlock();

    }

    public static void LinkedBlockingQueue() throws InterruptedException {
        LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
        queue.take();
    }


    static volatile boolean threadFlag = true;

    public static void Executors2() throws InterruptedException {
        ThreadPoolExecutor executorService = new ThreadPoolExecutor(
                1, 1
                , 10, TimeUnit.SECONDS
                , new LinkedBlockingQueue<>(1));
        executorService.execute(() -> {
            try {
                System.out.println(Thread.currentThread().hashCode());
//                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        executorService.execute(() -> System.out.println(Thread.currentThread().hashCode()));

        executorService.shutdown();
    }




    public static void Executors() throws InterruptedException {
        ThreadPoolExecutor executorService = new ThreadPoolExecutor(
                2, 4
                , 10, TimeUnit.SECONDS
                , new LinkedBlockingQueue<>(2));

        for (int i = 0; i < 6; i++) {
            System.out.println("===========" + i + "===========");
            Thread.sleep(1000);
            int finalI = i;
            executorService.execute(() -> {
                try {
                    while (threadFlag) {
                        System.out.println(finalI + " " + Thread.currentThread().getName() + " is running");
                        Thread.sleep(1000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });

        }


        Thread.sleep(10000);
        threadFlag = false;

        executorService.shutdown();

    }

    public static void exchanger() throws InterruptedException {

        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    String other = exchanger.exchange(Thread.currentThread().getName());
                    System.out.println(Thread.currentThread().getName() + ":" + other);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        String other = exchanger.exchange(Thread.currentThread().getName());
        System.out.println(Thread.currentThread().getName() + ":" + other);

    }


    public static void cyclicBarrier() throws BrokenBarrierException, InterruptedException {
        new Thread(() -> {
            try {
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("END");
        }).start();

        new Thread(() -> {
            try {
                Thread.sleep(3000);
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }).start();

        cyclicBarrier.await();
        System.out.println("MAIN END");
    }

    public static void countDownLatch() throws InterruptedException {

        new Thread(() -> countDownLatch.countDown()).start();
        new Thread(() -> {
            try {
                Thread.sleep(10030);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            countDownLatch.countDown();
        }).start();
        new Thread(() -> countDownLatch.countDown()).start();

        countDownLatch.await();

        System.out.println("END");


    }


    public static void test() throws InterruptedException {
        new Thread(() -> {
            reentrantLock.lock();
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            reentrantLock.unlock();
        }).start();

//        if (reentrantLock.tryLock(50, TimeUnit.SECONDS)) {
//            reentrantLock.unlock();
//        }

        reentrantLock.lock();
        reentrantLock.unlock();


    }

    public static void test1() {

        Thread t = new Thread(() -> {
            while (!Thread.interrupted()) {
                System.out.println("run");
            }
        });
        t.start();
        System.out.println(t.isAlive());
        t.interrupt();

    }

}
